﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DailyFx.AI
{
	internal class Zone : IEquatable<Zone>
	{
		/// <summary>
		///		Contains all <see cref="IBlock"/>s of this <see cref="Zone"/>
		/// </summary>
	//	private HashSet<IBlock> _blocks = new HashSet<IBlock>();
		private List<IBlock> _blocks = new List<IBlock>();

		/// <summary>
		///		Contains all <see cref="IObserver"/>s to <see cref="IBlock"/>s
		/// </summary>
		private List<IObserver> _observers = new List<IObserver>();



		/// <summary>
		///		C'tor, with unique zone id .
		/// </summary>
		public Zone ( Guid id )
		{
			this.Guid = id;
		}

		/// <summary>
		///		Gets the id of this <see cref="Zone"/> .
		/// </summary>
		public Guid Guid
		{
			get;
			private set;
		}

		/// <summary>
		///		Checks if this <see cref="Zone"/> contains the specified <see cref="IBlock"/>
		/// </summary>
		public bool hasBlock ( IBlock block)
		{
			return this._blocks.Contains ( block);
		}

		/// <summary>
		///		
		/// </summary>
		public IBlock getBlock ( IBlock block )
		{
			// return this._blocks.Find( x => x.Equals(block) );
			int i = this._blocks.IndexOf( block);
			if ( i >= 0)
				return this._blocks[ i];
			else
				return null;
		}

		/// <summary>
		///		Gets the <see cref="IBlock"/> selected by the <param name="block"/> reciever .
		/// </summary>
		public IBlock fetchBlock ( IBlock block )
		{
			// if ( !hasBlock( block) )
				// return null;

			IBlock _block = this.getBlock( block);
			if ( _blocks == null )
				return null;

			if ( _block.Version > block.Version)
			{
				return _block.clone () ;
			}

			// this is the block with higher version .
			return block;
		}

		/// <summary>
		///		
		/// </summary>
		public bool syncBlock ( IBlock block )
		{
			IBlock _block = this.getBlock( block);
			if ( _block == null )
				return false;

			if ( _block.Version < block.Version)
				return false;
			else 
				_block.copy( block );

			// todo: raises this modification .

			return true;
		}

		/// <summary>
		///		Adds a new block to this <see cref="Zone"/>
		/// </summary>
		public bool addBlock ( IBlock block)
		{
			if ( hasBlock( block) )
			{
				return false;
			}

			this._blocks.Add ( block) ;
			// this._blocks.Sort();

			// todo: raises this modification .

			return true;
		}

		/// <summary>
		///		Removes the specified <see cref="IBlock"/> from this <see cref="Zone"/>
		/// </summary>
		public bool takeBlock ( IBlock block )
		{
			// todo: raises this modification .
			//
			return this._blocks.Remove( block);
		}

		/// <summary>
		///		Clears all items of <see cref="IBlock"/>
		/// </summary>
		public void clear ()
		{
			this._blocks.Clear();
		}


		/// <summary>
		/// 
		/// </summary>
		public void registerObserver ( IObserver observer)
		{
			this._observers.Add (observer);
		}



		/// <summary>
		///		Equality .
		/// </summary>
		public bool Equals ( Zone other )
		{
			return this.Guid == other.Guid;
		}

		/// <summary>
		/// 
		/// </summary>
		public override bool Equals( object obj )
		{
			if ( !(obj is Zone) )
 				return false;

			return this.Equals( obj as Zone);
		}

		/// <summary>
		///		Hash Code .
		/// </summary>
		public override int GetHashCode ()
		{
			return this.Guid.GetHashCode();
		}

		/// <summary>
		///		To String .
		/// </summary>
		public override string ToString ()
		{
			return "Zone: " + this.Guid.ToString();
		}

	}
}
